﻿#ifndef __SS_RANDOM_H__
#define __SS_RANDOM_H__
#include "../ssBaseDefine.h"
#include "../ssSingleton.h"

namespace StarSeeker
{
///////////////////////////////////随机数/////////////////////////////////
class ssRandom
{
public:
	ssRandom(void);
	~ssRandom(void){}
	//随机种子
	void Seed(u32 sd);
	//随机
	i32 Rand(void);
	u32 RandU32(void);
	//指定范围随机,包括边界
	i32 Rand(i32 min, i32 max);
	u32 RandU32(u32 min, u32 max);
	//随机true or false
	bool RandBool(void);
	//范围随机偶数
	i32 RandEven(i32 min, i32 max);
	//随机1到分母之间的数，判断是否小于等于分子
	bool RandPercent(i32 numerator, i32 denominator);

private:
	u32	m_seed;
	u32	m_multiplier;
	u32	m_increment;
};
#define SS_RAND StarSeeker::ssSingle<ssRandom>::instance()
//////////////////////////////////////////////////////////////////////////
/////////////////////////按概率从一组数据中随机取值//////////////////////////
template<u32 NUM>
class ssProbabilityRandom
{
public:
	//数据结构
	struct Index_s
	{
		u32 index;		//数据索引
		i32 percent;	//概率百分比
	};

	ssProbabilityRandom()
	{
		m_maxCount = NUM;
		m_factCount = 0;
		m_counter = 0;
		m_denominator = 0;
	}
	//保存要随机的数据
	bool Push(u32 index, i32 p)
	{
		if (p>0 && m_factCount<m_maxCount)
		{
			m_index[m_factCount].index = index;
			m_index[m_factCount].percent = p;
			++m_factCount;
			return true;
		}
		return false;
	}
	//初始化概率，push调用完成后再调用
	void CovertPercent()
	{
		m_denominator = 0;
		for (u32 i=0; i<m_factCount; ++i)
		{
			m_denominator += m_index[i].percent;
			m_index[i].percent = m_denominator;
		}
		m_counter = m_factCount;
	}
	//清空
	void Empty(bool isZero=false)
	{
		m_factCount = 0;
		if (isZero)
		{
			memset(m_index, 0, sizeof(m_index));
		}
	}
	//返回一个随机的数据，不会重复
	u32 GetNextNotRepeat()
	{
		i32 rd = 0;
		u32 off = SS_INVAILD_U32;
		if (m_counter>0)
		{
			rd = SS_RAND->Rand()%m_denominator;
			for (u32 i=0; i<m_factCount; ++i)
			{
				if (m_index[i].index!=SS_INVAILD_U32 && rd<m_index[i].percent)
				{
					--m_counter;
					off = m_index[i].index;
					m_index[i].index = SS_INVAILD_U32;
					return off;
				}
			}
		}
		return off;
	}
	//返回一个随机的数据，会重复
	u32 GetNextRepeat()
	{
		i32 rd = 0;
		if (m_counter>1)
		{
			rd = SS_RAND->Rand()%m_denominator;
			for (u32 i=0; i<m_factCount; ++i)
			{
				if (rd<m_index[i].percent)
				{
					return m_index[i].index;
				}
			}
		}
		else if (m_counter==1)
		{
			return m_index[0].index;
		}
		return SS_INVAILD_U32;
	}
	//返回数据个数
	u32 GetCount() const
	{
		return m_factCount;
	}
private:
	Index_s		m_index[NUM];	//数据数组
	u32			m_maxCount;		//数据最大个数
	u32			m_factCount;	//数据实际个数
	i32			m_denominator;	//所有数据概率之和
	u32			m_counter;		//计数器
};
//////////////////////////////////////////////////////////////////////////
}
#endif
